import java.lang.Math;
import java.awt.Color;
import java.awt.event.*;
import java.util.Set;
import java.util.HashSet;
import java.util.Random;
import java.util.Collections;
import java.util.Arrays;
import java.util.TreeMap;

Map<Integer, List<Correspondance>> correspondances;
Map<Integer, Station> stations;
Map<String, List<Correspondance>> lignes;
Map<String, InformationTrafic> informationsTrafic;
List<PanneauAffichage> panneauxAffichage;
int traficTotal = 0;
Map<String, Color> colorMap = new HashMap<String, Color>();
double[][] heatMapStations;
double maxHeatStations;
//Icones
PImage metroImg, tramImg, rerImg, busImg, traficImg;

//Rectangle de selection
boolean drawRect = false;
float xPiv, yPiv, xOld, yOld, wRect = 0, hRect = 0, xOffset, yOffset;
float zoomX, zoomY;

//Graphique statique
boolean xyChart = false;
int xChart, yChart;
int nbUnionStation = 1;


//button
//b1
boolean heatMapStation = false;
String textB1;
color colorB1;
color colorTextB1;
//b2
boolean hideIcons = false;
String textB2;
color colorB2;
color colorTextB2;
//b3
boolean showPanneaux = false;
String textB3;
color colorB3;
color colorTextB3;
float angleSmall = 0.01;
float angleBig = 0.01;
//b4
boolean inputDone = false;
boolean inputMode = false;
String searchText = "";

void setup() {
  size(1280, 920, P3D);
  PFont arialMT = loadFont("ArialMT-60.vlw");
  textFont(arialMT);
  noLoop();

  //button
  colorB1 = color(100, 100, 100);
  colorTextB1 = color(200, 200, 200);
  textB1 = "Densité stations";
  colorB2 = color(100, 100, 100);
  colorTextB2 = color(200, 200, 200);
  textB2 = "Icônes";
  colorB3 = color(100, 100, 100);
  colorTextB3 = color(200, 200, 200);
  textB3 = "Panneaux d'affichage";

  heatMapStations = new double[width][height];
  zoomX = zoomY = 1.1;
  xOffset = ((1-zoomX)*width)/2;
  yOffset = ((1-zoomY)*height)/2;
  colorMode(RGB);
  //On charge l'ensemble des donnÃ©es
  correspondances = Correspondance.chargerCorrespondances(loadStrings("correspondances.csv"));
  lignes = Correspondance.chargerLignes(correspondances);
  stations = Station.chargerStations(loadStrings("stations.csv"));
  informationsTrafic = InformationTrafic.chargerInformationsTrafic(loadStrings("trafic_annuel.csv"));
  panneauxAffichage = PanneauAffichage.chargerPanneauxAffichage(loadStrings("panneaux_affichage.csv"));
  for (InformationTrafic it : informationsTrafic.values()) {
    traficTotal += it.trafic;
  }

  //Calcul du maximum de la heat map
  heatMapStations = new double[width][height];
  calcHeatMapStations();
  for (int i = 0; i < width; i++) {
    for (int j = 0; j < height; j++) {
      if (maxHeatStations < heatMapStations[i][j]) {
        maxHeatStations = heatMapStations[i][j];
      }
    }
  }

  addMouseWheelListener(new MouseWheelListener() {
    public void mouseWheelMoved(MouseWheelEvent mwe) {
      mouseWheel(mwe.getWheelRotation());
    }
  }
  );
  //On charge les icones
  metroImg = loadImage("icons/L_M.png");
  tramImg = loadImage("icons/L_T.png");
  rerImg = loadImage("icons/L_R.png");
  busImg = loadImage("icons/L_B.png");
  traficImg = loadImage("Trafic.png");
  noLoop();
}

void mouseWheel(int step) {
  if (((zoomX > 0.1 && zoomY > 0.1) || step > 0) && ((zoomX < 1.1 && zoomY < 1.1) || step < 0)) {
    float tmpX = mouseX*zoomX;
    float tmpY = mouseY*zoomY;
    zoomX = zoomX + step*0.05;
    zoomY = zoomY + step*0.05;
    xOffset = xOffset - mouseX*zoomX + tmpX;
    yOffset = yOffset - mouseY*zoomY + tmpY;
  }
  if ((zoomX < 1.1) && (zoomY >= 1.1) && (zoomX < zoomY) && (step > 0)) {
    float tmpX = mouseX*zoomX;
    zoomX = zoomX + step*0.05;
    xOffset = xOffset - mouseX*zoomX + tmpX;
  }
  if ((zoomY < 1.1) && (zoomX >= 1.1) && (zoomY < zoomX) && (step > 0)) {
    float tmpY = mouseY*zoomY;
    zoomY = zoomY + step*0.05;
    yOffset = yOffset - mouseY*zoomY + tmpY;
  }
  redraw();
}

boolean hoverRect(int x, int y, int width, int height) {
  if (mouseX >= x && mouseX <= x+width &&
    mouseY >= y && mouseY <= y+height) {
    return true;
  }
  else {
    return false;
  }
}

float getXNormal(Station s) {
  return ((s.longitude-Station.minlon)*(width)/(Station.maxlon-Station.minlon)-xOffset)/zoomX;
}

float getYNormal(Station s) {
  return ((height-((s.latitude-Station.minlat)*(height)/(Station.maxlat-Station.minlat)))-yOffset)/zoomY;
}

void draw() { 
  if (xyChart) {
    drawXYChart();
  }
  else {
    if (heatMapStation == true) {
      drawHeatMapStations();
    }
    else {
      background(210, 220, 230);
    }
    if (showPanneaux == true) {
      drawPanneaux();
    }

    if (!hideIcons) {
      drawStations();
      drawCorrespondance();
    }

    //Barre de recherche
    fill(0);
    textSize(14);
    text("Press 'ENTER' to search your station and press once more to valide.", 20, 20);
    text(searchText, 20, 45);
    //Dessin des boutons
    stroke(0);
    fill(colorB1);
    rect(1160, 100, 120, 30);
    fill(colorTextB1);
    textSize(14);
    text(textB1, 1165, 120);

    fill(colorB2);
    rect(1160, 140, 120, 30);
    fill(colorTextB2);
    textSize(14);
    text(textB2, 1165, 160);

    fill(colorB3);
    rect(1160, 180, 120, 30);
    fill(colorTextB3);
    textSize(14);
    text(textB3, 1165, 200);

    //Recherche de station
    if (inputDone && searchText.length() > 0) {
      for (Station s: stations.values()) {
        if (s.nom.toLowerCase().contains(searchText.toLowerCase())) {
          fill(255);
          float size = typeSize(s.type);
          ellipse(getXNormal(s), getYNormal(s), size, size);
        }
      }
    }

    //Rectangle de selection
    noFill();
    if (drawRect) {
      stroke(255, 0, 0);
      rect(xPiv, yPiv, wRect, hRect);
    }
    stroke(180, 180, 180);
    line(width*0.1, 0, width*0.1, height);
    line(width*0.9, 0, width*0.9, height);
    line(0, height*0.1, width, height*0.1);
    line(0, height*0.9, width, height*0.9);
  }
}

void drawXYChart() {
  background(210, 220, 230);
  //On cherche la station la plus proche
  float xMin, yMin, x, y;
  Station sMin = null;
  float dMin = Float.MAX_VALUE;
  for (Station s : stations.values()) {
    if (drawType(s.type)) {
      x = getXNormal(s);
      y = getYNormal(s);
      float d = dist(x, y, xChart, yChart);
      if (d < dMin) {
        dMin = d;
        sMin = s;
      }
    }
  }
  if (dMin > 40){
    xyChart = false;
    print("test");
    redraw(); 
  }
  xMin = getXNormal(sMin);
  yMin = getYNormal(sMin);

  //On ordonne les stations en fonction de leurs distance à la station cliquée
  Map<Float, InformationTrafic> orderedTrafic = new TreeMap<Float, InformationTrafic>();
  for (Station s : stations.values()) {
    InformationTrafic it = informationsTrafic.get(s.nom.toLowerCase().replace("-", " ").replace("Ã©", "e"));
    if (it != null && !orderedTrafic.values().contains(it)) {
      x = getXNormal(s);
      y = getYNormal(s);
      orderedTrafic.put(dist(x, y, xMin, yMin), it);
    }
  }
  //Dessin du graphique
  stroke(0);
  strokeWeight(2);
  textSize(14);
  text("Trafic annuel", 10, 0.5*height);
  text("Distance de " + sMin.nom, 0.5*width-textWidth("Distance de " + sMin.nom)/2, 0.9*height + 30);
  line(0.1*width, 0.1*height, 0.1*width, 0.9*height);
  line(0.1*width, 0.9*height, 0.9*width, 0.9*height);
  //traffic maximum
  int maxTrafic = 0;
  InformationTrafic trafics[] = orderedTrafic.values().toArray(new InformationTrafic[0]);
  for (int i = 0; i <= trafics.length - nbUnionStation; i = i + nbUnionStation) {
    int trafic=0;
    for (int n = 0; n < nbUnionStation; n++) {
      trafic += trafics[i+n].trafic;
    }
    if (maxTrafic < trafic) {
      maxTrafic = trafic;
    }
  }
  //Affichage des traffic
  strokeWeight(nbUnionStation);
  stroke(200, 50, 50);
  textSize(14);
  fill(0);
  for (  int i = 0; i <= trafics.length - nbUnionStation; i = i + nbUnionStation) {
    x = (0.1+0.8*i/orderedTrafic.size())*width + nbUnionStation * 2;
    int trafic=0;
    String text = new String();
    TreeMap<Integer, String> tmp = new TreeMap<Integer, String>();
    for (int n = 0; n < nbUnionStation; n++) {
      tmp.put(trafics[i+n].trafic, trafics[i+n].nomStation);
    }
    for (Entry<Integer, String> entry : tmp.descendingMap().entrySet()) {
      text += entry.getValue() + " : " + entry.getKey() + "\n";
      trafic += entry.getKey();
    }
    line(x, 0.9*height, x, (0.9-0.8*trafic/maxTrafic)*height);
    if (Math.abs(mouseX - (int)x) < nbUnionStation) {
      text(text, mouseX + 20, mouseY);
    }
  }
  //On affiche le nom de la station pointé par le curseur
}


void drawPanneaux() {
  float x, y;
  for (PanneauAffichage p : panneauxAffichage) {
    x = ((p.longitude-Station.minlon)*(width)/(Station.maxlon-Station.minlon)-xOffset)/zoomX;
    y = ((height-((p.latitude-Station.minlat)*(height)/(Station.maxlat-Station.minlat)))-yOffset)/zoomY;
    float size = (zoomX+zoomY)/2;
    if (p.format == 1) {
      //stroke(255, 0, 215);
      fill(255, 0, 215);
      angleSmall += 0.0001;
      pushMatrix();
      translate(x, y, 0);
      rotateX(PI/9);
      rotateY(PI/5 + angleSmall);
      box(5/size,3/size,1/size);
      popMatrix();
    }
    else {
      //stroke(0, 175, 255);
      fill(0, 175, 255);
      angleBig += 0.00003;
      pushMatrix();
      translate(x, y, 0);
      rotateX(PI/9);
      rotateY(PI/5 + angleBig);
      box(10/size,6/size,2/size);
      popMatrix();
    }
  }
  loop();
}


void drawStations() {
  //Affichage des stations
  float x, y;
  for (Station s : stations.values()) {
    //CoordonnÃ©es normalisÃ©s
    x = getXNormal(s);
    y = getYNormal(s); 
    PImage img = null;
    float size = typeSize(s.type);
    if (s.type == Station.METRO  && drawType(s.type)) {
      img = metroImg;
    }
    else if (s.type == Station.TRAM  && drawType(s.type)) {
      img = tramImg;
    }
    else if (s.type == Station.RER && drawType(s.type)) {
      img = rerImg;
    }
    else if (s.type == Station.BUS && drawType(s.type)) {
      img = busImg;
    }
    else {
      continue;
    }

    image(img, x - size/2, y - size/2, size, size);
    //image(img, x, y, 10/(zoomX+zoomY), 10/(zoomX+zoomY));
    //fill(255, 255, 255);
    //ellipse(x, y, 5/zoomX, 5/zoomY);
  }
  //Rectangle de selection
  noFill();
  if (drawRect) {
    stroke(255, 0, 0);
    rect(xPiv, yPiv, wRect, hRect);
  }
}

void calcHeatMapStations() {
  for (int i = 0; i < width; i++) {
    for (int j = 0; j < height; j++) {
      heatMapStations[i][j] = 0;
    }
  }
  //Calcul du tableau de chaleurs
  int r = (int) (20*(1/zoomX));
  for (Station s : stations.values()) {
    int x = int(getXNormal(s)), y = int(getYNormal(s));
    if (x < width && y < height && x > 0 && y > 0) {
      //println("Station : " + s.nom);
      for (int m = -r; m < r; m++) {
        for (int n = 0; dist(0, 0, m, n) < r; n++) {
          if (x+m < width && x+m > 0) {
            double heat = 5/(1+Math.sqrt(dist(0, 0, m, n)));
            //System.out.print(new DecimalFormat("0.00").format(heat) + " ");
            if (y+n < height) {
              //println("x " + (x+m) + " y " + (y+n) + " heat " + heat);
              heatMapStations[x+m][y+n] += heat;
            }
            if (y-n > 0 && n != 0) {
              heatMapStations[x+m][y-n] += heat;
            }
          }
        }
        //println();
      }
    }
  }
}

void drawHeatMapStations() {
  calcHeatMapStations();
  //On construit la heat map
  PImage bckGrnd = createImage(width, height, RGB);
  bckGrnd.loadPixels();
  for (int i = 0; i < width; i++) {
    for (int j = 0; j < height; j++) {
      if (heatMapStations[i][j] == 0) {
        bckGrnd.pixels[j*width+i] = color(50, 100, 150);
      }
      else {
        int heat = (int) (heatMapStations[i][j]*(255/maxHeatStations));
        //blanc
        if (heat >= 200) {
          bckGrnd.pixels[j*width+i] = color(heat, heat, heat);
        }
        //rouge
        else if (heat >= 150) {
          bckGrnd.pixels[j*width+i] = color(40+heat, 0, 0);
        }
        //jaune
        else if (heat >= 110) {
          bckGrnd.pixels[j*width+i] = color(55+heat, 55+heat, 0);
        }
        //vert
        else if (heat >= 80) {
          bckGrnd.pixels[j*width+i] = color(heat, 100+heat, 0);
        }
        //turquoise clair
        else if (heat >= 15) {
          bckGrnd.pixels[j*width+i] = color(0, 50+(heat*2), 255);
        }
        //bleu foncÃ©
        else if (heat > 0) {
          //println((int) (Math.pow(heatMapStations[i][j]*(255/max), 2)));
          bckGrnd.pixels[j*width+i] = color(0, 0, 150+heat*heat);
        }
        //bleu clair
        else {
          bckGrnd.pixels[j*width+i] = color(0, 25, 120);
        }
        //ellipse(i, j, 8, 8);
      }
    }
  }
  bckGrnd.updatePixels();
  //background(bckGrnd);
  image(bckGrnd,0 ,0 ,width ,height);
}


void drawCorrespondance() {
  fill(255, 0, 0);
  float x, y;
  //On cherche la station la plus proche
  Station sMin = null;
  float dMin = Float.MAX_VALUE;
  for (Station s : stations.values()) {
    if (drawType(s.type)) {
      x = getXNormal(s);
      y = getYNormal(s);
      float d = dist(x, y, mouseX, mouseY);
      if (d < dMin) {
        dMin = d;
        sMin = s;
      }
    }
  }
  if (dMin < 40) {
    textSize(30);
    //On cherche toutes les lignes passant par cette station
    //stroke(255, 255, 255);
    noStroke();
    List<Correspondance> cList = correspondances.get(sMin.identifiantStation);
    if (cList != null) {
      Set<String> cSet = new HashSet<String>();
      //On affiche toutes les stations des lignes
      int j = 0;
      for (Correspondance c : cList) {
        if (drawType(sMin.type) && !cSet.contains(c.nomLigne)) {
          cSet.add(c.nomLigne);
          PImage img = getImageLigne(c);
          if (img != null) {
            image(img, mouseX + textWidth(sMin.nom) + 10 + 35*j, mouseY - 25, 30, 30);
            j++;
          }
        }

        List<Correspondance> ligne = lignes.get(c.nomLigne);
        Color col = getCouleurLigne(ligne.get(0));
        fill(col.getRed(), col.getGreen(), col.getBlue());
        for (int i = 0; i < ligne.size(); i++) { 
          Station s = stations.get(ligne.get(i).identifiantStation);
          if (s == null) {
            System.err.println("Correspondance " + ligne.get(i).nomLigne + " : " + ligne.get(i).identifiantStation + " n'a pas de station");
          }
          else {
            x = getXNormal(s);
            y = getYNormal(s);
            if (drawType(s.type)) {
              float size = typeSize(s.type);
              ellipse(x, y, size, size);
            }
          }
        }
        strokeWeight(2);
        stroke(col.getRed(), col.getGreen(), col.getBlue());
        //drawLigne(new ArrayList<Correspondance>(ligne));
        drawLigne(sMin, c.nomLigne);
        strokeWeight(1);
      }
    }
    fill(200, 50, 50);
    if (drawType(sMin.type)) {
      InformationTrafic it = informationsTrafic.get(sMin.nom.toLowerCase().replace("-", " ").replace("Ã©", "e").replace("Ã¢", "a"));
      if (it != null) {
        float size = (float) (Math.log(1+(float) (it.trafic)/(traficTotal/informationsTrafic.size())))*100;
        image(traficImg, mouseX-size, mouseY-size, size, size);
      }
      text(sMin.nom, mouseX, mouseY);
    }
  }
}

boolean drawType(int type) {
  if (type == Station.METRO) {
    return true;
  }
  else if (type == Station.TRAM) {
    return true;
  }
  else if (type == Station.RER) {
    return true;
  }
  else if (type == Station.BUS) {
    return zoomX + zoomY < 0.2;
  }
  return false;
}

float typeSize(int type) {
  if (type == Station.METRO) {
    return (float) (Math.pow(Math.log(50/(zoomX+zoomY)+1)+1, 2));
  }
  else if (type == Station.TRAM) {
    return (float) (Math.pow(Math.log(20/(zoomX+zoomY)+1)+1, 2));
  }
  else if (type == Station.RER) {
    return (float) (Math.pow(Math.log(100/(zoomX+zoomY)+1)+1, 2));
  }
  else if (type == Station.BUS) {
    return (float) (Math.pow(Math.log(5/(zoomX+zoomY)+1)+1, 2));
  }
  return 0;
}

void drawLigne(Station s, String nomLigne) {
  String lines[] = null;
  if (s.type == Station.METRO) {
    lines = loadStrings("lignes/metro"+nomLigne+".csv");
  }
  else if (s.type == Station.TRAM) {
    lines = loadStrings("lignes/tram"+nomLigne+".csv");
  }
  else if (s.type == Station.RER) {
    lines = loadStrings("lignes/rer"+nomLigne+".csv");
  }
  else if (s.type == Station.BUS) {
    lines = loadStrings("lignes/bus"+nomLigne+".csv");
  }
  float x1, y1, x2, y2;
  if (lines != null) {
    for (int i = 1; i < lines.length - 1; i++) {
      String infos1[] = lines[i].split(";");
      Station s1 = stations.get(Integer.parseInt(infos1[0]));
      if (s1 != null) {
        int j = 1;
        String infos2[] = lines[i+j].split(";");
        Station s2 = stations.get(Integer.parseInt(infos2[0]));
        /*while (s2 == null && i+j < lines.length) {
         String infos2[] = lines[i+j].split(";");
         s2 = stations.get(Integer.parseInt(infos2[0]));
         j++;
         }*/
        if ((Integer.parseInt(infos1[6]) != 1 || i == 1) && s2 != null) {
          x1 = getXNormal(s1);
          y1 = getYNormal(s1);
          x2 = getXNormal(s2);
          y2 = getYNormal(s2);
          line(x1, y1, x2, y2);
        }
      }
    }
  }
}

/*void drawLigne(List<Correspondance> ligne) {
 Correspondance c = ligne.get(0);
 ligne.remove(0);
 float dMin = Float.MAX_VALUE, x1, y1, x = 0, y = 0, xMin = 0, yMin = 0;
 Station s = stations.get(c.identifiantStation);
 if (s != null) {
 x = getXNormal(s);
 y = getYNormal(s);
 for (Correspondance c1 : ligne) {
 Station s1 = stations.get(c1.identifiantStation);
 if (s1 != null) {
 x1 = getXNormal(s1);
 y1 = getYNormal(s1);
 if (dist(x, y, x1, y1) < dMin) {
 dMin = dist(x, y, x1, y1);
 xMin = x1;
 yMin = y1;
 }
 }
 }
 }
 if (dist(x, y, xMin, yMin) < 300) {
 line(x, y, xMin, yMin);
 if (ligne.size() > 1) {
 drawLigne(ligne);
 }
 }
 }*/

PImage getImageLigne(Correspondance c) {
  PImage img = null;
  if (c.type == Station.METRO) {
    img = loadImage("icons/M_"+c.nomLigne+".png");
  }
  else if (c.type == Station.RER) {
    img = loadImage("icons/RER_"+c.nomLigne+".png");
  }
  else if (c.type == Station.TRAM) {
    img = loadImage("icons/T_"+c.nomLigne.replace("T", "")+".png");
  }
  else if (c.type == Station.BUS) {
    img = loadImage("indices_result/"+c.nomLigne+"genRVB.png");
  }
  return img;
}

Color getCouleurLigne(Correspondance c) {
  Color c1 = colorMap.get(c.nomLigne);
  if (c1 == null) {
    color col;
    PImage img = getImageLigne(c);
    if (img == null) {
      Random r = new Random();
      col = color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
    }
    else {
      col = getCouleurImage(img);
    }
    //Using java Color object from awt to store the random chosen color
    c1 = new Color(int(red(col)), int(green(col)), int(blue(col)));
    colorMap.put(c.nomLigne, c1);
  }
  return c1;
}

color getCouleurImage(PImage img) {
  int i = 0;
  int j = 0;
  while (i < img.height && img.get (i, j) == color(0, 0, 0, 0)) {
    j  = 0;
    while (j < img.width && img.get (i, j) == color(0, 0, 0, 0)) {
      j++;
    }
    i++;
  }
  //PremiÃ¨re couleur != du blanc
  return img.get(max(i-1, 0), j);
}

void mousePressed() {
  if (mouseButton == RIGHT && !xyChart) {
    xyChart = true;
    xChart = mouseX;
    yChart = mouseY;
  }
  else if (xyChart && mouseButton == LEFT) {
    nbUnionStation = (nbUnionStation%10)+1;
  }
  else {
    if (keyPressed && keyCode == CONTROL) {
      xPiv = mouseX;
      yPiv = mouseY;
      drawRect = true;
    }
    else {
      xOld = mouseX;
      yOld = mouseY;
    }
    //button1
    if (hoverRect(1160, 100, 120, 30)) {
      if (heatMapStation) {
        heatMapStation = false;
        color colorT = colorTextB1;
        colorTextB1 = colorB1;
        colorB1 = colorT;
      }
      else {
        heatMapStation = true;
        color colorT = colorTextB1;
        colorTextB1 = colorB1;
        colorB1 = colorT;
      }
    }
    //button2
    else if (hoverRect(1160, 140, 120, 30)) {
      if (hideIcons) {
        hideIcons = false;
        color colorT = colorTextB2;
        colorTextB2 = colorB2;
        colorB2 = colorT;
      }
      else {
        hideIcons = true;
        color colorT = colorTextB2;
        colorTextB2 = colorB2;
        colorB2 = colorT;
      }
    }

    //button3
    else if (hoverRect(1160, 180, 120, 30)) {
      if (showPanneaux) {
        showPanneaux = false;
        color colorT = colorTextB3;
        colorTextB3 = colorB3;
        colorB3 = colorT;
        noLoop();
      }
      else {
        showPanneaux = true;
        color colorT = colorTextB3;
        colorTextB3 = colorB3;
        colorB3 = colorT;
        loop();
      }
    }
  }
}

void mouseDragged() {
  if (keyPressed && keyCode == CONTROL) {
    wRect = mouseX - xPiv;
    hRect = mouseY - yPiv;
  }
  else if(!xyChart){
    xOffset = xOffset - (mouseX - xOld)*zoomX;
    yOffset = yOffset - (mouseY - yOld)*zoomY;
    xOld = mouseX;
    yOld = mouseY;
  }
  redraw();
}

void mouseReleased() {
  if (keyPressed && keyCode == CONTROL) {
    float xOffsetT = wRect > 0 ? xPiv : xPiv + wRect;
    float yOffsetT = hRect > 0 ? yPiv : yPiv + hRect;
    float zoomXT = Math.abs(wRect/width)*zoomX;
    float zoomYT = Math.abs(hRect/height)*zoomY;
    if (zoomXT > 0.1 && zoomYT > 0.1) {
      xOffset = xOffset + xOffsetT*zoomX;
      yOffset = yOffset + yOffsetT*zoomY;
      zoomX = zoomXT;
      zoomY = zoomYT;
    }
    drawRect = false;
  }
  redraw();
}

void mouseMoved() {
  redraw();
}

void keyPressed() {
  //Reset des paramètres
  if (key == ' ' && !inputMode) {
    zoomY = zoomX = 1.1;
    xOffset = ((1-zoomX)*width)/2;
    yOffset = ((1-zoomY)*height)/2;
    searchText = "";
    inputDone = false;
    colorB1 = color(100, 100, 100);
    colorTextB1 = color(200, 200, 200);
    colorB2 = color(100, 100, 100);
    colorTextB2 = color(200, 200, 200);
    colorB3 = color(100, 100, 100);
    colorTextB3 = color(200, 200, 200);
    heatMapStation = false;
    hideIcons = false;
    showPanneaux = false;
    angleSmall = 0.01;
    angleBig = 0.01;
    inputDone = false;
    inputMode = false;
    xyChart = false;
    nbUnionStation = 1;
    noLoop();
  }
  if (key == ENTER || keyCode == ENTER) {
    if (inputMode) {
      inputMode = false;
      inputDone = true;
    }
    else {
      inputDone = false;
      searchText = "";
      inputMode = true;
    }
  }
  if (inputMode && key == BACKSPACE && searchText.length() > 0) {
    searchText = searchText.substring(0, searchText.length() - 1);
  }
  println(searchText);
  redraw();
}

void keyTyped() {
  if (inputMode && key != BACKSPACE && key != ENTER && key != ' ' && searchText.length() < 25) {
    searchText = searchText + key;
  }
  redraw();
}

